{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 8.3 量化金融 - 股票涨跌预测模型搭建"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 8.3.1 多因子模型搭建"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**1.引入之后需要用到的库**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tushare as ts  # 股票基本数据相关库\n",
    "import numpy as np  # 科学计算相关库\n",
    "import pandas as pd  # 科学计算相关库  \n",
    "import talib  # 股票衍生变量数据相关库\n",
    "import matplotlib.pyplot as plt  # 引入绘图相关库\n",
    "from sklearn.ensemble import RandomForestClassifier  # 引入分类决策树模型\n",
    "from sklearn.metrics import accuracy_score  # 引入准确度评分函数\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\") # 忽略警告信息，警告非报错，不影响代码执行"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**2.股票数据处理与衍生变量生成**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们这里将8.2节股票基本数据和股票衍生变量数据的相关代码汇总，方便之后的股票涨跌预测模型的搭建："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1.股票基本数据获取\n",
    "df = ts.get_k_data('000002',start='2015-01-01',end='2019-12-31')\n",
    "df = df.set_index('date')  # 设置日期为索引\n",
    "\n",
    "# 2.简单衍生变量构造\n",
    "df['close-open'] = (df['close'] - df['open'])/df['open']\n",
    "df['high-low'] = (df['high'] - df['low'])/df['low']\n",
    "\n",
    "df['pre_close'] = df['close'].shift(1)  # 该列所有往下移一行形成昨日收盘价\n",
    "df['price_change'] = df['close']-df['pre_close']\n",
    "df['p_change'] = (df['close']-df['pre_close'])/df['pre_close']*100\n",
    "\n",
    "# 3.移动平均线相关数据构造\n",
    "df['MA5'] = df['close'].rolling(5).mean()\n",
    "df['MA10'] = df['close'].rolling(10).mean()\n",
    "df.dropna(inplace=True)  # 删除空值\n",
    "\n",
    "# 4.通过Ta_lib库构造衍生变量\n",
    "df['RSI'] = talib.RSI(df['close'], timeperiod=12)  # 相对强弱指标\n",
    "df['MOM'] = talib.MOM(df['close'], timeperiod=5)  # 动量指标\n",
    "df['EMA12'] = talib.EMA(df['close'], timeperiod=12)  # 12日指数移动平均线\n",
    "df['EMA26'] = talib.EMA(df['close'], timeperiod=26)  # 26日指数移动平均线\n",
    "df['MACD'], df['MACDsignal'], df['MACDhist'] = talib.MACD(df['close'], fastperiod=12, slowperiod=26, signalperiod=9)  # MACD值\n",
    "df.dropna(inplace=True)  # 删除空值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>open</th>\n",
       "      <th>close</th>\n",
       "      <th>high</th>\n",
       "      <th>low</th>\n",
       "      <th>volume</th>\n",
       "      <th>code</th>\n",
       "      <th>close-open</th>\n",
       "      <th>high-low</th>\n",
       "      <th>pre_close</th>\n",
       "      <th>price_change</th>\n",
       "      <th>p_change</th>\n",
       "      <th>MA5</th>\n",
       "      <th>MA10</th>\n",
       "      <th>RSI</th>\n",
       "      <th>MOM</th>\n",
       "      <th>EMA12</th>\n",
       "      <th>EMA26</th>\n",
       "      <th>MACD</th>\n",
       "      <th>MACDsignal</th>\n",
       "      <th>MACDhist</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2019-12-25</th>\n",
       "      <td>30.40</td>\n",
       "      <td>30.29</td>\n",
       "      <td>30.63</td>\n",
       "      <td>30.18</td>\n",
       "      <td>685037.0</td>\n",
       "      <td>000002</td>\n",
       "      <td>-0.003618</td>\n",
       "      <td>0.014911</td>\n",
       "      <td>30.38</td>\n",
       "      <td>-0.09</td>\n",
       "      <td>-0.296248</td>\n",
       "      <td>30.878</td>\n",
       "      <td>30.075</td>\n",
       "      <td>63.075563</td>\n",
       "      <td>-0.02</td>\n",
       "      <td>29.908556</td>\n",
       "      <td>28.973211</td>\n",
       "      <td>0.935345</td>\n",
       "      <td>0.772958</td>\n",
       "      <td>0.162387</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-12-26</th>\n",
       "      <td>30.50</td>\n",
       "      <td>31.12</td>\n",
       "      <td>31.30</td>\n",
       "      <td>30.50</td>\n",
       "      <td>888790.0</td>\n",
       "      <td>000002</td>\n",
       "      <td>0.020328</td>\n",
       "      <td>0.026230</td>\n",
       "      <td>30.29</td>\n",
       "      <td>0.83</td>\n",
       "      <td>2.740178</td>\n",
       "      <td>30.896</td>\n",
       "      <td>30.387</td>\n",
       "      <td>68.890164</td>\n",
       "      <td>0.09</td>\n",
       "      <td>30.094932</td>\n",
       "      <td>29.132233</td>\n",
       "      <td>0.962699</td>\n",
       "      <td>0.810906</td>\n",
       "      <td>0.151793</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-12-27</th>\n",
       "      <td>31.23</td>\n",
       "      <td>31.00</td>\n",
       "      <td>31.32</td>\n",
       "      <td>30.81</td>\n",
       "      <td>703096.0</td>\n",
       "      <td>000002</td>\n",
       "      <td>-0.007365</td>\n",
       "      <td>0.016553</td>\n",
       "      <td>31.12</td>\n",
       "      <td>-0.12</td>\n",
       "      <td>-0.385604</td>\n",
       "      <td>30.760</td>\n",
       "      <td>30.672</td>\n",
       "      <td>67.220611</td>\n",
       "      <td>-0.68</td>\n",
       "      <td>30.234173</td>\n",
       "      <td>29.270586</td>\n",
       "      <td>0.963587</td>\n",
       "      <td>0.841442</td>\n",
       "      <td>0.122145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-12-30</th>\n",
       "      <td>31.35</td>\n",
       "      <td>31.57</td>\n",
       "      <td>31.79</td>\n",
       "      <td>31.02</td>\n",
       "      <td>915751.0</td>\n",
       "      <td>000002</td>\n",
       "      <td>0.007018</td>\n",
       "      <td>0.024823</td>\n",
       "      <td>31.00</td>\n",
       "      <td>0.57</td>\n",
       "      <td>1.838710</td>\n",
       "      <td>30.872</td>\n",
       "      <td>30.884</td>\n",
       "      <td>70.877814</td>\n",
       "      <td>0.56</td>\n",
       "      <td>30.439685</td>\n",
       "      <td>29.440913</td>\n",
       "      <td>0.998772</td>\n",
       "      <td>0.872908</td>\n",
       "      <td>0.125864</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-12-31</th>\n",
       "      <td>31.35</td>\n",
       "      <td>32.18</td>\n",
       "      <td>32.45</td>\n",
       "      <td>31.32</td>\n",
       "      <td>663497.0</td>\n",
       "      <td>000002</td>\n",
       "      <td>0.026475</td>\n",
       "      <td>0.036079</td>\n",
       "      <td>31.57</td>\n",
       "      <td>0.61</td>\n",
       "      <td>1.932214</td>\n",
       "      <td>31.232</td>\n",
       "      <td>31.057</td>\n",
       "      <td>74.233951</td>\n",
       "      <td>1.80</td>\n",
       "      <td>30.707426</td>\n",
       "      <td>29.643808</td>\n",
       "      <td>1.063618</td>\n",
       "      <td>0.911050</td>\n",
       "      <td>0.152567</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             open  close   high    low    volume    code  close-open  \\\n",
       "date                                                                   \n",
       "2019-12-25  30.40  30.29  30.63  30.18  685037.0  000002   -0.003618   \n",
       "2019-12-26  30.50  31.12  31.30  30.50  888790.0  000002    0.020328   \n",
       "2019-12-27  31.23  31.00  31.32  30.81  703096.0  000002   -0.007365   \n",
       "2019-12-30  31.35  31.57  31.79  31.02  915751.0  000002    0.007018   \n",
       "2019-12-31  31.35  32.18  32.45  31.32  663497.0  000002    0.026475   \n",
       "\n",
       "            high-low  pre_close  price_change  p_change     MA5    MA10  \\\n",
       "date                                                                      \n",
       "2019-12-25  0.014911      30.38         -0.09 -0.296248  30.878  30.075   \n",
       "2019-12-26  0.026230      30.29          0.83  2.740178  30.896  30.387   \n",
       "2019-12-27  0.016553      31.12         -0.12 -0.385604  30.760  30.672   \n",
       "2019-12-30  0.024823      31.00          0.57  1.838710  30.872  30.884   \n",
       "2019-12-31  0.036079      31.57          0.61  1.932214  31.232  31.057   \n",
       "\n",
       "                  RSI   MOM      EMA12      EMA26      MACD  MACDsignal  \\\n",
       "date                                                                      \n",
       "2019-12-25  63.075563 -0.02  29.908556  28.973211  0.935345    0.772958   \n",
       "2019-12-26  68.890164  0.09  30.094932  29.132233  0.962699    0.810906   \n",
       "2019-12-27  67.220611 -0.68  30.234173  29.270586  0.963587    0.841442   \n",
       "2019-12-30  70.877814  0.56  30.439685  29.440913  0.998772    0.872908   \n",
       "2019-12-31  74.233951  1.80  30.707426  29.643808  1.063618    0.911050   \n",
       "\n",
       "            MACDhist  \n",
       "date                  \n",
       "2019-12-25  0.162387  \n",
       "2019-12-26  0.151793  \n",
       "2019-12-27  0.122145  \n",
       "2019-12-30  0.125864  \n",
       "2019-12-31  0.152567  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看此时的df后五行\n",
    "df.tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**3.特征变量和目标变量提取**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = df[['close', 'volume', 'close-open', 'MA5', 'MA10', 'high-low', 'RSI', 'MOM', 'EMA12', 'MACD', 'MACDsignal', 'MACDhist']]\n",
    "y = np.where(df['price_change'].shift(-1)> 0, 1, -1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "首先强调最核心的一点：应该是今天的股价信息预测下一天的股价涨跌情况，所以y应该是下一天的股价变化情况。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其中Numpy库中的where()函数的使用方法如下所示：\n",
    "np.where(判断条件,满足条件的赋值,不满足条件的赋值)\n",
    "\n",
    "其中df['price_change'].shift(-1)则是利用shift()函数将price_change（股价变化）这一列往上移动一行，这样就获得了每一行对应的下一天股价涨跌情况。\n",
    "\n",
    "因此这里的判断条件就是下一天股价是否大于0，如果下一天股价涨了的我们则y赋值为数字1，下一天股价跌了的，则y赋值为数字-1。这个下一天的股价涨跌情况就是我们根据当天股票基本数据以及衍生变量预测的内容。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**3.训练集和测试集数据划分**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来，我们要将原始数据集进行分割，我们要注意到一点，训练集与测试集的划分要按照时间序列划分，而不是像之前利用train_test_split()函数进行划分。原因在于股票价格的变化趋势具有时间性，如果我们随机划分，则会破坏时间性特征，因为我们是根据当天数据来预测下一天的股价涨跌情况，而不是任意一天的股票数据来预测下一天的股价涨跌情况。\n",
    "因此，我们将前90%的数据作为训练集，后10%的数据作为测试集，代码如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_length = X.shape[0]  # shape属性获取X的行数和列数，shape[0]即表示行数 \n",
    "split = int(X_length * 0.9)\n",
    "\n",
    "X_train, X_test = X[:split], X[split:]\n",
    "y_train, y_test = y[:split], y[split:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**4.模型搭建**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,\n",
       "                       criterion='gini', max_depth=3, max_features='auto',\n",
       "                       max_leaf_nodes=None, max_samples=None,\n",
       "                       min_impurity_decrease=0.0, min_impurity_split=None,\n",
       "                       min_samples_leaf=10, min_samples_split=2,\n",
       "                       min_weight_fraction_leaf=0.0, n_estimators=10,\n",
       "                       n_jobs=None, oob_score=False, random_state=1, verbose=0,\n",
       "                       warm_start=False)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = RandomForestClassifier(max_depth=3, n_estimators=10, min_samples_leaf=10, random_state=1)\n",
    "model.fit(X_train, y_train)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 8.3.2 模型使用与评估"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**1.预测下一天的涨跌情况**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-1 -1 -1 -1  1  1  1  1  1  1  1  1  1  1  1  1  1 -1 -1  1  1  1  1  1\n",
      "  1  1  1 -1  1 -1 -1  1 -1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1\n",
      " -1  1  1  1  1 -1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1\n",
      "  1  1  1  1  1  1 -1 -1 -1 -1 -1 -1  1  1  1  1  1  1  1  1  1 -1 -1 -1\n",
      " -1 -1 -1 -1 -1 -1 -1 -1 -1]\n"
     ]
    }
   ],
   "source": [
    "y_pred = model.predict(X_test)\n",
    "print(y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>预测值</th>\n",
       "      <th>实际值</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>-1</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-1</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-1</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-1</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   预测值  实际值\n",
       "0   -1   -1\n",
       "1   -1   -1\n",
       "2   -1   -1\n",
       "3   -1   -1\n",
       "4    1    1"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = pd.DataFrame()  # 创建一个空DataFrame \n",
    "a['预测值'] = list(y_pred)\n",
    "a['实际值'] = list(y_test)\n",
    "a.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.51621099, 0.48378901],\n",
       "       [0.51550336, 0.48449664],\n",
       "       [0.5285002 , 0.4714998 ],\n",
       "       [0.5096509 , 0.4903491 ],\n",
       "       [0.47469396, 0.52530604]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看预测概率\n",
    "y_pred_proba = model.predict_proba(X_test)\n",
    "y_pred_proba[0:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**2.模型准确度评估**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.580952380952381\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "score = accuracy_score(y_pred, y_test)\n",
    "print(score)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.580952380952381"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 此外，我们还可以通过模型自带的score()函数记性打分，代码如下：\n",
    "model.score(X_test, y_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**3.分析数据特征的重要性**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.14523239, 0.09849436, 0.06155863, 0.0275968 , 0.05959848,\n",
       "       0.10019223, 0.02030875, 0.19567289, 0.0664462 , 0.06374818,\n",
       "       0.09227566, 0.06887541])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.feature_importances_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>特征</th>\n",
       "      <th>特征重要性</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>MOM</td>\n",
       "      <td>0.195673</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>close</td>\n",
       "      <td>0.145232</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>high-low</td>\n",
       "      <td>0.100192</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>volume</td>\n",
       "      <td>0.098494</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>MACDsignal</td>\n",
       "      <td>0.092276</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>MACDhist</td>\n",
       "      <td>0.068875</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>EMA12</td>\n",
       "      <td>0.066446</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>MACD</td>\n",
       "      <td>0.063748</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>close-open</td>\n",
       "      <td>0.061559</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>MA10</td>\n",
       "      <td>0.059598</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>MA5</td>\n",
       "      <td>0.027597</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>RSI</td>\n",
       "      <td>0.020309</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            特征     特征重要性\n",
       "7          MOM  0.195673\n",
       "0        close  0.145232\n",
       "5     high-low  0.100192\n",
       "1       volume  0.098494\n",
       "10  MACDsignal  0.092276\n",
       "11    MACDhist  0.068875\n",
       "8        EMA12  0.066446\n",
       "9         MACD  0.063748\n",
       "2   close-open  0.061559\n",
       "4         MA10  0.059598\n",
       "3          MA5  0.027597\n",
       "6          RSI  0.020309"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 通过如下代码可以更好的展示特征及其特征重要性：\n",
    "features = X.columns  \n",
    "importances = model.feature_importances_\n",
    "a = pd.DataFrame()\n",
    "a['特征'] = features\n",
    "a['特征重要性'] = importances\n",
    "a = a.sort_values('特征重要性', ascending=False)\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 8.3.3 参数调优"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import GridSearchCV  # 网格搜索合适的超参数\n",
    "# 指定分类器中参数的范围\n",
    "parameters = {'n_estimators':[5, 10, 20], 'max_depth':[2, 3, 4, 5], 'min_samples_leaf':[5, 10, 20, 30]}\n",
    "new_model = RandomForestClassifier(random_state=1)  # 构建分类器\n",
    "grid_search = GridSearchCV(new_model, parameters, cv=6, scoring='accuracy')  # cv=6表示交叉验证6次，scoring='roc_auc'表示以ROC曲线的AUC评分作为模型评价准则, 默认为'accuracy', 即按准确度评分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'max_depth': 3, 'min_samples_leaf': 10, 'n_estimators': 10}"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grid_search.fit(X_train, y_train)  # 传入数据\n",
    "grid_search.best_params_  # 输出参数的最优值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 8.3.4 收益回测曲线绘制"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>strategy</th>\n",
       "      <th>origin</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2019-12-25</th>\n",
       "      <td>1.396445</td>\n",
       "      <td>1.015761</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-12-26</th>\n",
       "      <td>1.358180</td>\n",
       "      <td>1.043595</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-12-27</th>\n",
       "      <td>1.363417</td>\n",
       "      <td>1.039571</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-12-30</th>\n",
       "      <td>1.338347</td>\n",
       "      <td>1.058685</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-12-31</th>\n",
       "      <td>1.312488</td>\n",
       "      <td>1.079142</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            strategy    origin\n",
       "date                          \n",
       "2019-12-25  1.396445  1.015761\n",
       "2019-12-26  1.358180  1.043595\n",
       "2019-12-27  1.363417  1.039571\n",
       "2019-12-30  1.338347  1.058685\n",
       "2019-12-31  1.312488  1.079142"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_test['prediction'] = model.predict(X_test)\n",
    "X_test['p_change'] = (X_test['close'] - X_test['close'].shift(1)) / X_test['close'].shift(1)\n",
    "\n",
    "X_test['origin'] = (X_test['p_change'] + 1).cumprod()\n",
    "X_test['strategy'] = (X_test['prediction'].shift(1) * X_test['p_change'] + 1).cumprod()\n",
    "\n",
    "X_test[['strategy', 'origin']].tail()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 通过如下代码将收益情况删除空值后可视化，并设置X轴刻度自动倾斜：\n",
    "X_test[['strategy', 'origin']].dropna().plot()\n",
    "plt.gcf().autofmt_xdate()\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
